﻿#include<iostream>
using namespace std;
#include<functional>


//template<class T>
//class SmartPtr {
//public:
//	SmartPtr(T* ptr) 
//		:_ptr(ptr)
//	{} 
//
//
//	~SmartPtr() {
//		cout << "delete[] "  << _ptr << endl;
//		delete[] _ptr;
//	}
//private:
//	T* _ptr;
//};
//
//
//double Divide(double x, double y) {
//	if (y == 0) throw string("The Zero is Divided");
//	cout << x / y << endl;
//	return x / y;
//}
//
//void Func(double x, double y) {
//	cout << "int* arr1 = new int[10]   int* arr2 = new int[20]; " << endl;
//	SmartPtr<int> sp1 = new int[10];
//	SmartPtr<int> sp2 = new int[20];
//
//	Divide(x, y);
//}
//
//
//int main() {	
//	try {
//		double a, b;
//		cin >> a >> b;
//		Func(a, b);
//	}
//	catch (const string& errStr) {
//		cout << errStr << endl;
//	}
//	catch (...) {
//		cout << "Unknown Exception" << endl;
//	}
//	
//
//	return 0;
//}







//namespace myspace{
//	template<class T>
//	class auto_ptr {
//	public:
//		auto_ptr(T* ptr)
//			:_ptr(ptr)
//		{}
//
//		auto_ptr(auto_ptr<T>& sp)
//			:_ptr(sp._ptr)
//		{
//			// 管理权转移
//			sp._ptr = nullptr;
//		}
//
//		auto_ptr<T>& operator=(auto_ptr<T>& ap) {
//			// 检测是否为自己给自己赋值
//			if (this != &ap) {
//				// 释放当前对象中资源
//				if (_ptr)
//					delete _ptr;
//				// 转移ap中资源到当前对象中
//				_ptr = ap._ptr;
//				ap._ptr = NULL;
//			}
//			return *this;
//		}
//
//		~auto_ptr() {
//			if (_ptr) {
//				cout << "delete:" << _ptr << endl;
//				delete _ptr;
//			}
//		}
//
//		// 像指针⼀样使用
//		T& operator*() {
//			return *_ptr;
//		}
//
//		T* operator->() {
//			return _ptr;
//		}
//
//	private:
//		T* _ptr;
//	};
//}




namespace myspace {

	template<class T>
	class unique_ptr {
	public:
		unique_ptr(T* ptr)
			:_ptr(ptr)
		{}

		unique_ptr(unique_ptr<T>& up) = delete;

		unique_ptr(unique_ptr<T>&& up) 
			:_ptr(up._ptr)
		{
			up._ptr = nullptr;
		}

		unique_ptr<T>& operator=(unique_ptr<T>& up) = delete;

		unique_ptr<T>& operator=(unique_ptr<T>&& up) {
			delete _ptr;
			_ptr = up._ptr;
			up._ptr = nullptr;
		}

		~unique_ptr() {
			if (_ptr) {
				cout << "delete:" << _ptr << endl;
				delete _ptr;
			}
		}

		// 像指针⼀样使用
		T& operator*() {
			return *_ptr;
		}

		T* operator->() {
			return _ptr;
		}

	private:
		T* _ptr;
	};
}




//#include<memory>
//int main() {
//	
//	int* p1 = new int[10];
//	//myspace::unique_ptr<int> up1(p1);
//	//myspace::unique_ptr<int> up2(p1);
//
//	std::unique_ptr<int> up3(p1);
//	std::unique_ptr<int> up4(p1);
//
//
//	return 0;
//}




//#include<memory>
//int main() {
//
//	int* p1 = new int[10]{ 1,2,3,4,5,6,7,8,9,10 };
//
//	//构造
//	std::shared_ptr<int> sp1(p1);
//	//拷贝构造
//	std::shared_ptr<int> sp2(sp1);
//	//拷贝构造
//	std::shared_ptr<int> sp3(sp2);
//
//	//拷贝赋值
//	std::shared_ptr<int> sp4;
//	sp4 = sp1;
//
//
//	return 0;
//}



namespace myspace {

	template<class T>
	class shared_ptr {
	public:
		shared_ptr<T>() {
			_ptr = nullptr;
			_pcount = new int(1);
		}
		
		template<class D>
		shared_ptr(T* ptr, D del)
			:_ptr(ptr),
			_pcount(new int(1)),
			_del(del)
		{}


		explicit shared_ptr(T* ptr)
		 	:_ptr(ptr),
			_pcount(new int(1))
		{}

		shared_ptr(const shared_ptr<T>& sp) 
			:_ptr(sp._ptr),
			_pcount(sp._pcount)
		{
			++(*_pcount);
		}

		shared_ptr<T>& operator=(const shared_ptr<T>& sp) {

			//自己给自己赋值
			//1.  sp1 = sp1
			//2.  sp1 和 sp2 共管一份资源

			if (_ptr == sp._ptr) {
				if (--(*_pcount) == 0) {
					_del(_ptr);
					delete _pcount;
				}

				_ptr = sp._ptr;
				_pcount = sp._pcount;
				++(*_pcount);
			}

			return *this;

		}

		~shared_ptr() {
			if (--(*_pcount) == 0) {
				_del(_ptr);
				delete _pcount;
			}
		}

		T& operator*() {
			return *_ptr;
		}

		T* operator->() {
			return _ptr;
		}

	private:
		T* _ptr;//指向资源
		int* _pcount;//指向引用计数变量
		function<void(T*)> _del = []() {delete _del; };//默认是删除的是delete 如果需要delete[] 就特化或者传入对应删除器
	};


}

//class Date {
//public:
//	Date(int year, int month, int day)
//		:_year(year),
//		_month(month),
//		_day(day)
//	{}
//
//	int _year;
//	int _month;
//	int _day;
//};
//
//#include<vector>
//int main() {
//
//	
//	/*std::shared_ptr<Date> sp1 = make_shared<Date>(2025, 5, 26);
//	cout << sp1->_year << " " << sp1->_month << " " << sp1->_day << endl;
//
//
//	std::shared_ptr<int> sp2 = make_shared<int>(3);*/
//
//
//	/*int* p1 = new int[10];
//	std::shared_ptr<int[]> sp3 = make_shared<int[]>(1, 2, 3, 4);*/
//
//	vector<int> v1 = { 1,2,3,4,5,6,7,8,9,10 };
//	shared_ptr<vector<int>> sp4 = make_shared<vector<int>>(v1);
//
//	for (auto x : *sp4) {
//		cout << x << " ";
//	}
//	cout << endl;
//	return 0;
//}


//template<class T>
//struct listNode
//{
//	T _data = T();
//
//	/*listNode<T>* _prev;
//	listNode<T>* _next;*/
//
//	/*std::shared_ptr<listNode<T>> _prev;
//	std::shared_ptr<listNode<T>> _next;*/
//
//	std::weak_ptr<listNode<T>> _prev;
//	std::weak_ptr<listNode<T>> _next;
//
//
//	/*listNode(T data = T(), listNode<T>* prev = nullptr, listNode<T>* next = nullptr)
//		:_data(data),
//		_prev(prev),
//		_next(next)
//	{}*/
//
//	~listNode() {
//		cout << "~listNode" << endl;
//	}
//};
//
//
//template<class T>
//class weak_ptr
//{
//public:
//	weak_ptr()
//	{}
//	weak_ptr(const shared_ptr<T>& sp)
//		:_ptr(sp.get())
//	{}
//	weak_ptr<T>& operator=(const shared_ptr<T>& sp) {
//		_ptr = sp.get();
//		return *this;
//	}
//private:
//	T* _ptr = nullptr;
//};
//
//
//int main() {
//	
//	
//	std::shared_ptr<listNode<int>> sp1(new listNode<int>); 
//	std::shared_ptr<listNode<int>> sp2(new listNode<int>);
//
//	sp1->_next = sp2;
//	sp2->_prev = sp1;
//
//
//	return 0;
//}





class Date {
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year),
		_month(month),
		_day(day)
	{}

	~Date() {
		cout << "~Date" << endl;
	}

	int _year;
	int _month;
	int _day;
	
};


//int main() {
//
//	Date* PD = new Date[10];
//
//	//std::shared_ptr<Date> sp1(PD, [](Date* ptr) {delete[] ptr;});
//	//std::shared_ptr<Date[]> sp1(PD);
//
//	int* p1 = new int[10];
//	myspace::shared_ptr<int> sp2(p1, [](int* ptr) {delete[] ptr; });
//
//	myspace::shared_ptr<Date> sp3(PD, [](Date* pdate) {delete[] pdate; });
//
//	return 0;
//}


struct ManyDateDelete{
	void operator()(Date* pdate) {
		delete[] pdate;
	}
};

template<class T>
void DateDelete(T* pdate) {
	delete[] pdate;
}


//int main() {
//
//	Date* PD = new Date[10];
//	//std::unique_ptr<Date, ManyDateDelete> up1(PD);
//
//	std::unique_ptr<Date, decltype(DateDelete<Date>)> up2(PD, DateDelete<Date>);
//	//std::unique_ptr<Date, void(*)(Date*)> up2(PD, DateDelete);
//	
//	auto dateDel = [](Date* pdate) {delete[] pdate; };
//	std::unique_ptr<Date, decltype(dateDel)> up3(PD,dateDel);
//	
//	
// 
// 
// 
// 
// 
// 
// 
// 
//	
//	return 0;
//}

int main() {


	std::unique_ptr<Date[], ManyDateDelete> up1(new Date[10]);





	return 0;
}